----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    12:06:36 10/17/2014 
-- Design Name: 
-- Module Name:    ConstellationMap_Tx - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity ConstellationMap_Tx is
    Port ( clk : in  STD_LOGIC;
           ce : in  STD_LOGIC;
			  rst : in STD_LOGIC;
           modType : in  STD_LOGIC_VECTOR (2 downto 0);
           dataIn : in  STD_LOGIC_VECTOR (5 downto 0);
			  dataAvailable_in :  in  STD_LOGIC;
           dataOut_R : out  STD_LOGIC_VECTOR (3 downto 0);
           dataOut_I : out  STD_LOGIC_VECTOR (3 downto 0);
			  dataAvailable_out :  out  STD_LOGIC 
	 );
end ConstellationMap_Tx;

architecture Behavioral of ConstellationMap_Tx is

--signal sig_qam2_dataIn : std_logic_vector(0 downto 0) := (others=>'0');
signal sig_qam4_dataIn : std_logic_vector(1 downto 0) := (others=>'0');
signal sig_qam8_dataIn : std_logic_vector(2 downto 0) := (others=>'0');
signal sig_qam16_dataIn : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam32_dataIn : std_logic_vector(4 downto 0) := (others=>'0');
signal sig_qam64_dataIn : std_logic_vector(5 downto 0) := (others=>'0');

signal sig_qam2_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam2_dataOut_R_z1 : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam4_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam8_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam16_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam32_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam64_dataOut_R : std_logic_vector(3 downto 0) := (others=>'0');

signal sig_qam2_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam2_dataOut_I_z1 : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam4_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam8_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam16_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam32_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');
signal sig_qam64_dataOut_I : std_logic_vector(3 downto 0) := (others=>'0');

signal sig_dataIn_valid : std_logic := '0';
signal sig_dataIn_valid_z1 : std_logic := '0';
signal sig_modType_z1 : std_logic_vector(2 downto 0) := (others=>'0');
signal sig_dataAvailable_in_z1 : std_logic := '0';
signal sig_dataAvailable_in_z2 : std_logic := '0';

component QAM4_Real IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM4_Real;

component QAM4_Imag IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM4_Imag;

component QAM8_Real IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM8_Real;

component QAM8_Imag IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM8_Imag;

component QAM16_Real IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM16_Real;

component QAM16_Imag IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM16_Imag;

component QAM32_Real IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM32_Real;

component QAM32_Imag IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM32_Imag;

component QAM64_Real IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM64_Real;

component QAM64_Imag IS
  PORT (
    clka : IN STD_LOGIC;
    ena : IN STD_LOGIC;
    addra : IN STD_LOGIC_VECTOR(5 DOWNTO 0);
    douta : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
  );
END component QAM64_Imag;

begin

QAM4_R : QAM4_Real
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam4_dataIn,
	 douta => sig_qam4_dataOut_R
	);
 
 QAM4_I : QAM4_Imag
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam4_dataIn,
	 douta => sig_qam4_dataOut_I
	);
 
 QAM8_R : QAM8_Real
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam8_dataIn,
	 douta => sig_qam8_dataOut_R
	);
 
 QAM8_I : QAM8_Imag
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam8_dataIn,
	 douta => sig_qam8_dataOut_I
	);
 
 QAM16_R : QAM16_Real
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam16_dataIn,
	 douta => sig_qam16_dataOut_R
	);
 
 QAM16_I : QAM16_Imag
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam16_dataIn,
	 douta => sig_qam16_dataOut_I
	);
 
 QAM32_R : QAM32_Real
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam32_dataIn,
	 douta => sig_qam32_dataOut_R
	);
 
 QAM32_I : QAM32_Imag
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam32_dataIn,
	 douta => sig_qam32_dataOut_I
	);

 QAM64_R : QAM64_Real
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam64_dataIn,
	 douta => sig_qam64_dataOut_R
	);
 
 QAM64_I : QAM64_Imag
	PORT map (
	 clka => clk,
	 ena => ce,
	 addra => sig_qam64_dataIn,
	 douta => sig_qam64_dataOut_I
	);
	
-----------------------------------------------------------------------------------

	process(clk, ce, dataAvailable_in, rst)
	begin
	
		if (rising_edge(clk)) then			
			if (dataAvailable_in = '1') then
	--			if (rst = '1') then
	--				sig_qam4_dataIn <= (others=>'0');
	--				sig_qam8_dataIn <= (others=>'0');
	--				sig_qam16_dataIn <= (others=>'0');
	--				sig_qam32_dataIn <= (others=>'0');
	--				sig_qam64_dataIn <= (others=>'0');
	--
	--				sig_qam2_dataOut_R <= (others=>'0');
	--				sig_qam2_dataOut_R_z1 <= (others=>'0');
	--				sig_qam4_dataOut_R  <= (others=>'0');
	--				sig_qam8_dataOut_R <= (others=>'0');
	--				sig_qam16_dataOut_R <= (others=>'0');
	--				sig_qam32_dataOut_R <= (others=>'0');
	--				sig_qam64_dataOut_R <= (others=>'0');
	--
	--				sig_qam2_dataOut_I <= (others=>'0');
	--				sig_qam2_dataOut_I_z1 <= (others=>'0');
	--				sig_qam4_dataOut_I <= (others=>'0');
	--				sig_qam8_dataOut_I <= (others=>'0');
	--				sig_qam16_dataOut_I <= (others=>'0');
	--				sig_qam32_dataOut_I <= (others=>'0');
	--				sig_qam64_dataOut_I <= (others=>'0');
	--
	--				sig_dataIn_valid <= '0';
	--				sig_dataIn_valid_z1 <= '0';
	--				sig_modType_z1 <= (others=>'0');		
	--
	--				dataOut_R <= (others=>'0');
	--				dataOut_I <= (others=>'0');	
					
				if (ce = '1') then
				
					sig_dataIn_valid <= '0';
					
					case modType is
						when "000" =>
							if ( unsigned(dataIn) <= 1 ) then
								if (dataIn(0) = '0') then
									sig_qam2_dataOut_R <= "0001";
									sig_qam2_dataOut_I <= (others=>'0');							
								elsif (dataIn(0) = '1') then
									sig_qam2_dataOut_R <= "1111";
									sig_qam2_dataOut_I <= (others=>'0');								
								end if;
								sig_dataIn_valid <= '1';
							end if;
							
						when "001" =>
							if ( unsigned(dataIn) <= 3 ) then
								sig_qam4_dataIn <= dataIn(1 downto 0);		
								sig_dataIn_valid <= '1';							
							end if;
												
						when "010" =>
							if ( unsigned(dataIn) <= 7 ) then
								sig_qam8_dataIn <= dataIn(2 downto 0);	
								sig_dataIn_valid <= '1';							
							end if;
												
						when "011" =>
							if ( unsigned(dataIn) <= 15 ) then
								sig_qam16_dataIn <= dataIn(3 downto 0);	
								sig_dataIn_valid <= '1';							
							end if;
												
						when "100" =>
							if ( unsigned(dataIn) <= 31 ) then
								sig_qam32_dataIn <= dataIn(4 downto 0);	
								sig_dataIn_valid <= '1';							
							end if;
												
						when "101" =>
							if ( unsigned(dataIn) <= 63 ) then
								sig_qam64_dataIn <= dataIn(5 downto 0);	
								sig_dataIn_valid <= '1';							
							end if;
												
						when others =>
							-- do nothing at this moment
					end case;

					sig_qam2_dataOut_R_z1 <= sig_qam2_dataOut_R;
					sig_qam2_dataOut_I_z1 <= sig_qam2_dataOut_I;
					sig_dataIn_valid_z1 <= sig_dataIn_valid;
					sig_modType_z1 <= modType;
					sig_dataAvailable_in_z1 <= dataAvailable_in;
					sig_dataAvailable_in_z2 <= sig_dataAvailable_in_z1;
					dataAvailable_out <= sig_dataAvailable_in_z2;
					
					if (sig_dataIn_valid_z1 = '1') then
						case sig_modType_z1 is
							when "000" =>
								dataOut_R <= sig_qam2_dataOut_R_z1;
								dataOut_I <= sig_qam2_dataOut_I_z1;	
								
							when "001" =>
								dataOut_R <= sig_qam4_dataOut_R;
								dataOut_I <= sig_qam4_dataOut_I;			
													
							when "010" =>
								dataOut_R <= sig_qam8_dataOut_R;
								dataOut_I <= sig_qam8_dataOut_I;	
													
							when "011" =>
								dataOut_R <= sig_qam16_dataOut_R;
								dataOut_I <= sig_qam16_dataOut_I;							
													
							when "100" =>
								dataOut_R <= sig_qam32_dataOut_R;
								dataOut_I <= sig_qam32_dataOut_I;							
													
							when "101" =>
								dataOut_R <= sig_qam64_dataOut_R;
								dataOut_I <= sig_qam64_dataOut_I;						
													
							when others =>
								dataOut_R <= (others=>'0');
								dataOut_I <= (others=>'0');
						end case;
					else
						dataOut_R <= (others=>'0');
						dataOut_I <= (others=>'0');
					end if;
				end if;
			else
				dataAvailable_out <= '0';
			end if;	
		end if;
	end process;
end Behavioral;

